<!DOCTYPE html>
<html class="client-nojs vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-0 vector-toc-not-available vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-0 skin-theme-clientpref-day vector-sticky-header-enabled" lang="de" dir="ltr"><head>
<meta charset="UTF-8">
<title>Diamond-square Algorithmus</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="./_res_/favicon.png">
<link rel="canonical" href="https://de.wikipedia.org/wiki/Diamond-square_Algorithmus"> <link href="./_mw_/ext.cite.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.math.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.pygments.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.wikimediamessages.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/skins.vector.icons.css" rel="stylesheet" type="text/css">
<link href="./_mw_/skins.vector.search.codex.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/skins.vector.styles.css" rel="stylesheet" type="text/css">
<meta name="ResourceLoaderDynamicStyles" content="">
<link href="./_mw_/ext.gadget.citeRef.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.defaultPlainlinks.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiCommonHide.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiCommonLayout.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiCommonStyle.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiDarkmode.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiResponsive.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.specialSearch.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" type="text/css" href="./_mw_/site.styles.css">
<link rel="stylesheet" type="text/css" href="./_mw_/noscript.css">
<link rel="stylesheet" type="text/css" href="./_res_/footer.css">
<link rel="stylesheet" type="text/css" href="./_res_/vector-2022.css">
</head>
<body class="skin--responsive skin-vector skin-vector-search-vue mediawiki ltr sitedir-ltr mw-hide-empty-elt ns-0 ns-subject page-Diamond-square_Algorithmus rootpage-Diamond-square_Algorithmus skin-vector-2022 action-view">
<div class="mw-page-container">
<div class="mw-page-container-inner">
<div class="mw-content-container">
<main id="content" class="mw-body">
<header class="mw-body-header vector-page-titlebar">
<h1 id="firstHeading" class="firstHeading mw-first-heading"><span class="mw-page-title-main">Diamond-square Algorithmus</span></h1>
</header>
<a id="top"></a>
<div id="bodyContent" class="vector-body ve-init-mw-desktopArticleTarget-targetContainer" aria-labelledby="firstHeading" data-mw-ve-target-container="">
<div id="contentSub">
<div id="mw-content-subtitle"></div>
</div>
<div id="mw-content-text" class="mw-body-content mw-content-ltr" lang="de" dir="ltr"><div class="mw-content-ltr mw-parser-output" lang="de" dir="ltr"><p>Der <b>Diamond-square Algorithmus</b> ist ein Verfahren, das in der <a href="Computergrafik" title="Computergrafik">Computergrafik</a> eingesetzt wird, um <a href="H%C3%B6henfeld" title="Höhenfeld">Höhenfelder</a> zu erzeugen. Er stellt eine <a href="Zweidimensional" class="mw-redirect" title="Zweidimensional">2-dimensionale</a> Verallgemeinerung der Mittelpunktverschiebung dar. Der Algorithmus wurde erstmals 1982 von <a href="Alain_Fournier_(Informatiker)" title="Alain Fournier (Informatiker)">Fournier</a>, Fussell und Carpenter auf der <a href="SIGGRAPH" title="SIGGRAPH">SIGGRAPH</a> 1982 vorgestellt<sup id="cite_ref-fournier1982computer_1-0" class="reference"><a href="#cite_note-fournier1982computer-1"><span class="cite-bracket">[</span>1<span class="cite-bracket">]</span></a></sup>. Der Name geht zurück auf Gavin S. P. Miller<sup id="cite_ref-miller1986definition_2-0" class="reference"><a href="#cite_note-miller1986definition-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup>.
</p>
<div class="mw-heading mw-heading2"><h2 id="Funktionsweise">Funktionsweise</h2></div>
<p>Ausgangspunkt für die Generierung einer fraktalen Landschaft auf Basis des Diamond-square Algorithmus ist ein Quadrat. Jeder Ecke des Quadrats wird ein Höhenwert zugeordnet. Der Algorithmus zerlegt das Quadrat <a href="Rekursiv" class="mw-redirect" title="Rekursiv">rekursiv</a> in kleinere Quadrate, wobei der Höhenwert des Mittelpunkts als Mittelwert der vier Eckpunkte, plus einer zufälligen Verschiebung, definiert wird. Analog wird der Höhenwert der <a href="Seitenhalbierende" title="Seitenhalbierende">Seitenhalbierenden</a> eines Quadrats als Mittelwert der vier horizontal umgebenden Punkte, plus einer zufälligen Verschiebung, definiert. Die Verschiebung ist <a href="Normalverteilung" title="Normalverteilung">Normalverteilt</a> mit einem <a href="Mittelwert" title="Mittelwert">Mittelwert</a> von 0 und nimmt mit der Größe der Rechtecke ab. Die Mittelpunkte und Seitenhalbierende bilden die Eckpunkte der neuen Rechtecke. Ausnahme von der Regel zur Generierung der neuen Punkte bilden die vier Außenseiten des ursprünglichen Rechtecks, die jeweils nach der eindimensionalen Mittelpunktverschiebung generiert werden<sup id="cite_ref-fournier1982computer_1-1" class="reference"><a href="#cite_note-fournier1982computer-1"><span class="cite-bracket">[</span>1<span class="cite-bracket">]</span></a></sup>.
</p><p>Für den Diamond-square Algorithmus kommt ein 3x3-Raster, ein 5x5-Raster, ein 9x9-Raster, ein 17x17-Raster oder allgemein ein <a href="Quadratisch" class="mw-redirect" title="Quadratisch">quadratisches</a> Raster infrage, wo die Breite und Höhe gleich <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle 2^{n}+1}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<msup>
<mn>2</mn>
<mrow class="MJX-TeXAtom-ORD">
<mi>n</mi>
</mrow>
</msup>
<mo>+</mo>
<mn>1</mn>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle 2^{n}+1}</annotation>
</semantics>
</math></span><img src="./_assets_/eb734a37dd21ce173a46342d1cc64c92/e8e2d6ae605ac99baf648b70d204a3c9803a4d9b.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.505ex; width:6.384ex; height:2.509ex;" alt="{\displaystyle 2^{n}+1}" loading="lazy"></span> mit einer positiven <a href="Ganze_Zahl" title="Ganze Zahl">ganzen Zahl</a> <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle n}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>n</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle n}</annotation>
</semantics>
</math></span><img src="./_assets_/eb734a37dd21ce173a46342d1cc64c92/a601995d55609f2d9f5e233e36fbe9ea26011b3b.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:1.395ex; height:1.676ex;" alt="{\displaystyle n}" loading="lazy"></span> ist. Jede <a href="Iteration" title="Iteration">Iteration</a> unterteilt jedes Quadrat in 4 gleich große Quadrate mit halber Seitenlänge und besteht aus 2 Schritten:
</p>
<ul><li><i>Karoschritt</i>: Für jedes Quadrat des Rasters wird ein zufälliger Wert im Mittelpunkt erzeugt, wo sich die beiden Diagonalen des Quadrats schneiden. Der Wert für den Mittelpunkt wird berechnet, indem der Durchschnitt der Werte der 4 Ecken des Quadrats gebildet und ein zufälliger Betrag addiert wird. Dadurch entstehen Quadrate, die auf der Ecke stehen (<i>Karos</i>).</li>
<li><i>Quadratschritt</i>: Für jedes quadratische Karo wird ein zufälliger Wert im Mittelpunkt erzeugt, wo sich die beiden Diagonalen des Karos schneiden. Der Wert für den Mittelpunkt wird berechnet, indem der Durchschnitt der Werte der 4 Ecken des Karos gebildet und ein zufälliger Betrag addiert wird, der im gleichen Bereich liegt wie im Karoschritt. Dadurch entstehen wieder Quadrate, die parallel zum Raster sind.</li></ul>
<p>Jede <a href="Iteration" title="Iteration">Iteration</a> unterteilt jedes Quadrat also in 4 gleich große Quadrate mit halber Seitenlänge. Wenn die Prozedur 2-mal ausgeführt wird, entstehen aus jedem Quadrat <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle 4^{2}=16}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<msup>
<mn>4</mn>
<mrow class="MJX-TeXAtom-ORD">
<mn>2</mn>
</mrow>
</msup>
<mo>=</mo>
<mn>16</mn>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle 4^{2}=16}</annotation>
</semantics>
</math></span><img src="./_assets_/eb734a37dd21ce173a46342d1cc64c92/891f0a31ba5eed6c31d8879cd3aa3aa66ecd2ea4.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:7.64ex; height:2.676ex;" alt="{\displaystyle 4^{2}=16}" loading="lazy"></span> kleinere Quadrate mit gleicher Seitenlänge. Wenn die Prozedur <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle k}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<mi>k</mi>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle k}</annotation>
</semantics>
</math></span><img src="./_assets_/eb734a37dd21ce173a46342d1cc64c92/c3c9a2c7b599b37105512c5d570edc034056dd40.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:1.211ex; height:2.176ex;" alt="{\displaystyle k}" loading="lazy"></span>-mal ausgeführt wird, entstehen aus jedem Quadrat <span class="mwe-math-element mwe-math-element-inline"><span class="mwe-math-mathml-inline mwe-math-mathml-a11y" style="display: none;"><math xmlns="http://www.w3.org/1998/Math/MathML" alttext="{\displaystyle 4^{k}}">
<semantics>
<mrow class="MJX-TeXAtom-ORD">
<mstyle displaystyle="true" scriptlevel="0">
<msup>
<mn>4</mn>
<mrow class="MJX-TeXAtom-ORD">
<mi>k</mi>
</mrow>
</msup>
</mstyle>
</mrow>
<annotation encoding="application/x-tex">{\displaystyle 4^{k}}</annotation>
</semantics>
</math></span><img src="./_assets_/eb734a37dd21ce173a46342d1cc64c92/563b380d4a8d0bb311093679b5696422a1c6f66d.svg" class="mwe-math-fallback-image-inline mw-invert skin-invert" aria-hidden="true" style="vertical-align: -0.338ex; width:2.251ex; height:2.676ex;" alt="{\displaystyle 4^{k}}" loading="lazy"></span> kleinere Quadrate mit gleicher Seitenlänge.<sup id="cite_ref-3" class="reference"><a href="#cite_note-3"><span class="cite-bracket">[</span>3<span class="cite-bracket">]</span></a></sup>
</p><p>Folgende Abbildung zeigt die ersten zwei Iterationen des Algorithmus für ein 5x5-Raster:
</p><p>
</p><p>Dabei werden vier Schritte in der Reihenfolge <i>Karoschritt, Quadratschritt, Karoschritt, Quadratschritt</i> ausgeführt. Schon vorhandene Punkte sind schwarz, neu erzeugte Punkte sind gelb dargestellt.
</p>
<div class="mw-heading mw-heading2"><h2 id="Programmierung">Programmierung</h2></div>
<p>Das folgende Beispiel in der <a href="Programmiersprache" title="Programmiersprache">Programmiersprache</a> <a href="C-Sharp" title="C-Sharp">C#</a> zeigt die Implementierung des Diamond-square Algorithmus. Das Höhenfeld wird als <a href="Zweidimensional" class="mw-redirect" title="Zweidimensional">zweidimensionales</a> Hintergrundbild des Hauptfensters dargestellt. Die berechneten Werte entsprechen den Farbwerten der <a href="Pixel" title="Pixel">Pixel</a> einer <i>Bitmap</i>.<sup id="cite_ref-4" class="reference"><a href="#cite_note-4"><span class="cite-bracket">[</span>4<span class="cite-bracket">]</span></a></sup>
</p>
<table class="wikitable left mw-collapsible mw-collapsed font-size: 105.3%;">
<tbody><tr>
<td style="text-align:left; font-size: 95%;"><b>Code-Schnipsel</b>
</td></tr>
<tr>
<td>
<div class="mw-highlight mw-highlight-lang-c# mw-content-ltr" dir="ltr"><pre><span></span><span class="k">using</span><span class="w"> </span><span class="nn">System</span><span class="p">;</span>
<span class="k">using</span><span class="w"> </span><span class="nn">System.Drawing</span><span class="p">;</span>
<span class="k">using</span><span class="w"> </span><span class="nn">System.Windows.Forms</span><span class="p">;</span>
<span class="k">namespace</span><span class="w"> </span><span class="nn">DiamondSquare</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">DiamondSquare</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Diese Methode berechnet die Werte mit dem Diamond-square Algorithmus</span>
<span class="w"> </span><span class="c1">// Gegen ist die Seitenlänge des Quadrats, der Bereich für die zufälligen Werte und der Wert für die 4 Ecken des Quadrats</span>
<span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="kt">double</span><span class="p">[,]</span><span class="w"> </span><span class="n">CalculateValues</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">length</span><span class="p">,</span><span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">roughness</span><span class="p">,</span><span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">seed</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Initialisiert den Wert der 4 Ecken des Quadrats</span>
<span class="w"> </span><span class="kt">double</span><span class="p">[,]</span><span class="w"> </span><span class="n">values</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">double</span><span class="p">[</span><span class="n">length</span><span class="p">,</span><span class="w"> </span><span class="n">length</span><span class="p">];</span><span class="w"> </span><span class="c1">// Initialisiert das zweidimensionale Array für die Werte des quadratischen Rasters</span>
<span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">seed</span><span class="p">;</span><span class="w"> </span><span class="c1">// Wert der Ecke links oben</span>
<span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">seed</span><span class="p">;</span><span class="w"> </span><span class="c1">// Wert der Ecke links unten</span>
<span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">seed</span><span class="p">;</span><span class="w"> </span><span class="c1">// Wert der Ecke rechts oben</span>
<span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">seed</span><span class="p">;</span><span class="w"> </span><span class="c1">// Wert der Ecke rechts unten</span>
<span class="w"> </span><span class="n">Random</span><span class="w"> </span><span class="n">random</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Random</span><span class="p">();</span><span class="w"> </span><span class="c1">// Initialisiert den Zufallsgenerator</span>
<span class="w"> </span><span class="c1">// Diese for-Schleife definiert die Iterationsschritte des Algorithmus</span>
<span class="w"> </span><span class="c1">// In jedem Iterationsschritt wird die Seitenlänge der Teilquadrate und der Bereich für die zufälligen Werte halbiert, bis die Seitenlänge kleiner als 2 ist</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">sideLength</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="n">sideLength</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span><span class="w"> </span><span class="n">sideLength</span><span class="w"> </span><span class="o">/=</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="n">roughness</span><span class="w"> </span><span class="o">/=</span><span class="w"> </span><span class="mf">2.0</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">halfLength</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sideLength</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
<span class="w"> </span><span class="c1">// In diesen zwei for-Schleifen werden die Werte für den Karoschritt berechnet</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">sideLength</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">sideLength</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Berechnet den Mittelwert der 4 Ecken des Teilquadrats</span>
<span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">average</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">values</span><span class="p">[</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">]</span><span class="w"> </span><span class="c1">// Wert der Ecke links oben</span>
<span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">sideLength</span><span class="p">]</span><span class="w"> </span><span class="c1">// Wert der Ecke links unten</span>
<span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">sideLength</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">]</span><span class="w"> </span><span class="c1">// Wert der Ecke rechts oben</span>
<span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">sideLength</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">sideLength</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">4.0</span><span class="p">;</span><span class="w"> </span><span class="c1">// Wert der Ecke rechts unten</span>
<span class="w"> </span><span class="n">average</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="p">(</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">roughness</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">random</span><span class="p">.</span><span class="n">NextDouble</span><span class="p">())</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">roughness</span><span class="p">;</span><span class="w"> </span><span class="c1">// Addiert einen zufälligen Wert im Bereich von -roughness bis +roughness zum Mittelwert</span>
<span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">halfLength</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">halfLength</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">average</span><span class="p">;</span><span class="w"> </span><span class="c1">// Setzt den Wert für den Mittelpunkt des Teilquadrats</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="c1">// In diesen zwei for-Schleifen werden die Werte für den Quadratschritt berechnet</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">halfLength</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">halfLength</span><span class="p">)</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">sideLength</span><span class="p">;</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">sideLength</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Berechnet den Mittelwert der 4 Ecken des Karos</span>
<span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">average</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">values</span><span class="p">[(</span><span class="n">x</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">halfLength</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">length</span><span class="p">)</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">length</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">]</span><span class="w"> </span><span class="c1">// Wert der linken Ecke</span>
<span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">values</span><span class="p">[(</span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">halfLength</span><span class="p">)</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">length</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">]</span><span class="w"> </span><span class="c1">// Wert der rechten Ecke</span>
<span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">halfLength</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">length</span><span class="p">)</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">length</span><span class="p">]</span><span class="w"> </span><span class="c1">// Wert der oberen Ecke</span>
<span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">halfLength</span><span class="p">)</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">length</span><span class="p">])</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">4.0</span><span class="p">;</span><span class="w"> </span><span class="c1">// Wert der unteren Ecke</span>
<span class="w"> </span><span class="n">average</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="p">(</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">roughness</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">random</span><span class="p">.</span><span class="n">NextDouble</span><span class="p">())</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">roughness</span><span class="p">;</span><span class="w"> </span><span class="c1">// Addiert einen zufälligen Wert im Bereich von -roughness bis +roughness zum Mittelwert</span>
<span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">average</span><span class="p">;</span><span class="w"> </span><span class="c1">// Setzt den Wert für den Mittelpunkt des Karos</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="c1">// Sonderfall für die linke Kante des Quadrats</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">average</span><span class="p">;</span><span class="w"> </span><span class="c1">// Setzt den entsprechenden Punkt auf der rechten Kante auf denselben Wert</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="c1">// Sonderfall für die obere Kante des Quadrats</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">average</span><span class="p">;</span><span class="w"> </span><span class="c1">// Setzt den entsprechenden Punkt auf der unteren Kante auf denselben Wert</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">values</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span>
<span class="w"> </span><span class="c1">// Klasse für das Hauptfenster</span>
<span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="k">partial</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">MainForm</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">Form</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">private</span><span class="w"> </span><span class="n">Bitmap</span><span class="w"> </span><span class="n">bitmap</span><span class="p">;</span>
<span class="w"> </span>
<span class="w"> </span><span class="k">private</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">length</span><span class="p">;</span>
<span class="w"> </span><span class="k">private</span><span class="w"> </span><span class="kt">double</span><span class="p">[,]</span><span class="w"> </span><span class="n">values</span><span class="p">;</span><span class="w"> </span><span class="c1">// Zweidimensionales Array für die Werte des quadratischen Rasters</span>
<span class="w"> </span>
<span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="nf">MainForm</span><span class="p">()</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Random</span><span class="w"> </span><span class="n">random</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Random</span><span class="p">();</span><span class="w"> </span><span class="c1">// Initialisiert den Zufallsgenerator</span>
<span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">257</span><span class="p">;</span><span class="w"> </span><span class="c1">// Seitenlänge des Quadrats, es ist 2^8 + 1 = 257</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">roughness</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">64</span><span class="p">;</span><span class="w"> </span><span class="c1">// Bereich für die zufälligen Werte</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">seed</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">128</span><span class="p">;</span><span class="w"> </span><span class="c1">// Wert für die 4 Ecken des Quadrats</span>
<span class="w"> </span>
<span class="w"> </span><span class="n">DiamondSquare</span><span class="w"> </span><span class="n">diamondSquare</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">DiamondSquare</span><span class="p">();</span><span class="w"> </span><span class="c1">// Erzeugt ein Objekt der Klasse DiamondSquare</span>
<span class="w"> </span><span class="n">values</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">diamondSquare</span><span class="p">.</span><span class="n">CalculateValues</span><span class="p">(</span><span class="n">length</span><span class="p">,</span><span class="w"> </span><span class="n">roughness</span><span class="p">,</span><span class="w"> </span><span class="n">seed</span><span class="p">);</span><span class="w"> </span><span class="c1">// Aufruf der Methode, die die Werte für das quadratische Raster berechnet und zurückgibt</span>
<span class="w"> </span><span class="n">bitmap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Bitmap</span><span class="p">(</span><span class="n">length</span><span class="p">,</span><span class="w"> </span><span class="n">length</span><span class="p">);</span><span class="w"> </span><span class="c1">// Erzeugt ein quadratisches Bitmap mit der gegebenen Seitenlänge</span>
<span class="w"> </span><span class="n">BackgroundImage</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bitmap</span><span class="p">;</span><span class="w"> </span><span class="c1">// Setzt die Bitmap als Hintergrundbild des Hauptfensters.</span>
<span class="w"> </span>
<span class="w"> </span><span class="n">InitializeComponent</span><span class="p">();</span>
<span class="w"> </span><span class="n">Text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"Diamond-square Algorithmus"</span><span class="p">;</span>
<span class="w"> </span><span class="n">Width</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">800</span><span class="p">;</span>
<span class="w"> </span><span class="n">Height</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">800</span><span class="p">;</span>
<span class="w"> </span><span class="n">Paint</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">OnPaint</span><span class="p">;</span><span class="w"> </span><span class="c1">// Verknüpft die Ereignisbehandlungsmethode mit dem Paint Ereignis des Hauptfensters.</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span>
<span class="w"> </span><span class="c1">// Diese Methode wird aufgerufen, wenn das Hauptfenster gezeichnet wird und setzt die Pixel des Bitmaps</span>
<span class="w"> </span><span class="k">private</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">OnPaint</span><span class="p">(</span><span class="kt">object</span><span class="w"> </span><span class="n">sender</span><span class="p">,</span><span class="w"> </span><span class="n">PaintEventArgs</span><span class="w"> </span><span class="n">e</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Diese for-Schleifen durchlaufen die Pixel des Bitmaps</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">length</span><span class="p">;</span><span class="w"> </span><span class="n">x</span><span class="o">++</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">length</span><span class="p">;</span><span class="w"> </span><span class="n">y</span><span class="o">++</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">bitmap</span><span class="p">.</span><span class="n">SetPixel</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">,</span><span class="w"> </span><span class="n">Color</span><span class="p">.</span><span class="n">FromArgb</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">values</span><span class="p">[</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">],</span><span class="w"> </span><span class="mi">0</span><span class="p">));</span><span class="w"> </span><span class="c1">// Setzt den Farbwert des Pixels</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></tbody></table>
<div class="mw-heading mw-heading2"><h2 id="Mögliche_Implementierung_in_unterschiedlichen_Dimensionen"><span id="M.C3.B6gliche_Implementierung_in_unterschiedlichen_Dimensionen"></span>Mögliche Implementierung in unterschiedlichen Dimensionen</h2></div>
<p>Es ist möglich, den Algorithmus in verschiedene Dimensionen zu übertragen und somit unterschiedliche Resultate zu erzielen. Hierbei wird eine n-dimensionale Einheit mit Tiefe versehen. Das heißt, dass für jede berechnete n-dimensionale Koordinate ein Wert, meist von 0 bis 1, vorhanden ist. Die optische Darstellung kann man entweder mit einer Verschiebung in der nächsten Dimensionsachse oder eine Farbe bzw. Transparenz realisieren. Hierbei ist die zweidimensionale Implementierung namensgebend.
</p>
<dl><dt>Beispiele</dt>
<dd></dd></dl>
<p>Bei einer dreidimensionalen Implementierung kann man sich zum Beispiel eine Karte für die Dichte von Nebel vorstellen. Hierbei werden unterschiedliche Areale unterschiedlich viel Licht absorbieren.
</p>
<div class="mw-heading mw-heading2"><h2 id="Kritik">Kritik</h2></div>
<p>Gavin S. P. Miller hat den Diamond-square Algorithmus kritisiert, da er, im Gegensatz zu dem von ihm vorgestellten <a href="Square-square_Algorithmus" title="Square-square Algorithmus">Square-square Algorithmus</a>, zu auffälligen Artefakten in der generierten Landschaft führt<sup id="cite_ref-miller1986definition_2-1" class="reference"><a href="#cite_note-miller1986definition-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup>.
</p><p>Fraktale Landschaften im Allgemeinen stehen in der Kritik, da sie zwar eine gute Approximation für Bergzüge liefern, die Landschaften jedoch – stellt man sie auf den Kopf – statistisch identisch sind<sup id="cite_ref-5" class="reference"><a href="#cite_note-5"><span class="cite-bracket">[</span>5<span class="cite-bracket">]</span></a></sup>. In der Realität lagern sich jedoch beispielsweise Sedimente in Talsenken ab, wodurch diese abflachen. Unter anderem haben Musgrave, Kolb und Mace unter Berücksichtigung von <a href="Erosion_(Geologie)" title="Erosion (Geologie)">Erosion</a>seffekten eine Weiterentwicklung fraktaler Landschaften entwickelt, die in der Lage ist, Landschaften zu erzeugen, die wesentlich realitätsnäher sind.
</p>
<div class="mw-heading mw-heading2"><h2 id="Weblinks">Weblinks</h2></div>
<ul><li>Async Drink: <a rel="nofollow" class="external text" href="https://asyncdrink.com/blog/diamond-square-algorithm">Generating landscapes with the Diamond Square algorithm</a></li>
<li>Robert C. Martin, The Clean Code Blog <a rel="nofollow" class="external text" href="https://blog.cleancoder.com/uncle-bob/2017/01/09/DiamondSquare.html">TDD Lesson - Terrain Generation</a></li>
<li><a rel="nofollow" class="external text" href="https://gist.github.com/awilki01/83b65ad852a0ab30192af07cda3d7c0b">Diamond-square Implementierung in C#</a></li>
<li><a rel="nofollow" class="external text" href="https://github.com/A1essandro/Diamond-And-Square">Diamond-square Implementierung in PHP</a></li>
<li>Fractal terrain generator: <a rel="nofollow" class="external text" href="https://spbooth.github.io/xmountains/">Xmountains</a></li></ul>
<div class="mw-heading mw-heading2"><h2 id="Einzelnachweise">Einzelnachweise</h2></div>
<ol class="references">
<li id="cite_note-fournier1982computer-1"><span class="mw-cite-backlink">↑ <sup><a href="#cite_ref-fournier1982computer_1-0">a</a></sup> <sup><a href="#cite_ref-fournier1982computer_1-1">b</a></sup></span> <span class="reference-text">A. Fournier,D. Fussell und L. Carpenter: <i>Computer rendering of stochastic models</i> In: Communications of the ACM, Band 25, Nr. 6, 1982, S. 371–384</span>
</li>
<li id="cite_note-miller1986definition-2"><span class="mw-cite-backlink">↑ <sup><a href="#cite_ref-miller1986definition_2-0">a</a></sup> <sup><a href="#cite_ref-miller1986definition_2-1">b</a></sup></span> <span class="reference-text">Gavin S. P. Miller: <i>The definition and rendering of terrain maps</i> In: ACM SIGGRAPH Computer Graphics, Band 20, Nr. 4, 1986, S. 39–48</span>
</li>
<li id="cite_note-3"><span class="mw-cite-backlink"><a href="#cite_ref-3">↑</a></span> <span class="reference-text">Robert C. Pendleton: <a rel="nofollow" class="external text" href="https://web.archive.org/web/20060420054134/http://www.gameprogrammer.com/fractal.html#diamond">Generating Random Fractal Terrain</a></span>
</li>
<li id="cite_note-4"><span class="mw-cite-backlink"><a href="#cite_ref-4">↑</a></span> <span class="reference-text">GitHub: <a rel="nofollow" class="external text" href="https://gist.github.com/awilki01/83b65ad852a0ab30192af07cda3d7c0b">Diamond-Square Algorithm for Generating Terrain (C#)</a></span>
</li>
<li id="cite_note-5"><span class="mw-cite-backlink"><a href="#cite_ref-5">↑</a></span> <span class="reference-text">F.K. Musgrave, C.E. Kolb und R.S. Mace: <i>The synthesis and rendering of eroded fractal terrains</i> In: ACM SIGGRAPH Computer Graphics, Band 23, Nr. 3, 1989, S. 41–50</span>
</li>
</ol></div><!--htdig_noindex--><div><div class="zim-footer">
Dieser Artikel wurde von <a class="external text" title="Zuletzt bearbeitet am 2024-06-17" href="https://de.wikipedia.org/wiki/?title=Diamond-square_Algorithmus&oldid=245976557">Wikipedia</a> herausgegeben. Der Text ist unter <a class="external text" href="https://creativecommons.org/licenses/by-sa/4.0/deed.de">Creative Commons Attribution-Share Alike 4.0</a> verfügbar, sofern nicht anders angegeben. Für die Mediendateien können zusätzliche Bedingungen gelten.
</div>
</div><!--/htdig_noindex--></div>
</div>
</main>
</div>
</div>
</div>
<script src="./_webp_/webpHandler.js"></script>
</body></html>